package javase_class_250907;

/**
 * ClassName: AbstractExample
 * Package: javase_class_250907
 * Description:
 *
 * @Author harkjeans
 * @Create 2025/9/7 16:39
 * @Version 1.0
 */
/**
 * 为什么要用抽象类？（设计意义）
 * 代码复用与模板方法模式：
 * 抽象类可以将多个子类的共同代码（如 eat(), sleep()）提升到父类中，避免代码重复。
 * 它可以定义一个操作的算法骨架（模板），而将一些步骤延迟到子类中实现。这就是著名的模板方法模式。
 * 制定规范与契约：
 * 抽象类通过抽象方法，强制要求所有子类都必须拥有某些行为，确保了系统的一致性。它定义了一个“是什么”（接口），而子类负责“怎么做”（实现）。
 * 实现多态：
 * 如上例所示，我们可以使用抽象父类 Animal 的引用来指向具体子类（Dog, Cat）的对象。在调用 makeSound() 时，JVM 会根据实际对象的类型来决定执行哪个方法，这是多态的典型应用。
 *
 * abstract 关键字不能和哪些关键字共存？
 * private：抽象方法需要被重写，而 private 方法对子类不可见，矛盾。
 * final：final 方法禁止被重写，而抽象方法要求被重写，矛盾。
 * static：static 方法属于类，不依赖于对象，无法被重写（只能被隐藏），而抽象方法需要子类对象来实现，矛盾。
 *
 */
public class AbstractExample {
    public static void main(String[] args) {
        // Animal animal = new Animal("Generic Animal"); // 错误！不能实例化抽象类

        Animal myDog = new Dog("Rex");
        Animal myCat = new Cat("Whiskers");

        myDog.sleep(); // 输出: Rex is sleeping. Zzz...
        myDog.makeSound(); // 输出: Rex says: Woof! Woof!

        myCat.sleep(); // 输出: Whiskers is sleeping. Zzz...
        myCat.makeSound(); // 输出: Whiskers says: Meow! Meow!
    }
}
// 1. 抽象类
abstract class Animal {
    private String name;

    public String getName() {
        return name;
    }

    public Animal(String name) {
        this.name = name;
    }

    // 2. 普通方法
    public void sleep() {
        System.out.println(name + " is sleeping. Zzz...");
    }

    // 3. 抽象方法 - 子类必须实现
    public abstract void makeSound();
}

// 4. 非抽象子类 Dog - 必须实现抽象方法
class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造方法
    }

    @Override
    public void makeSound() { // 提供了具体实现
        System.out.println(getName() + " says: Woof! Woof!");
    }
}

// 5. 非抽象子类 Cat - 必须实现抽象方法
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() { // 提供了不同的实现
        System.out.println(getName() + " says: Meow! Meow!");
    }
}

